﻿using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace PlotDesigner
{
    public partial class PlotNode : UserControl
    {
        const int w = 10, h = 8;
        int x, y;
        //true=正在移动、flase=没有移动
        public bool moveFlag = false;
        /// <summary>
        /// 定义属性：剧情名
        /// </summary>
        public string plotName
        {
            set => label_PlotName.Text = value;
            get => label_PlotName.Text;
        }
        /// <summary>
        /// 定义属性：是否为结局
        /// </summary>
        public bool isEnded
        {
            set => checkbox_isEnded.Checked = value;
            get => checkbox_isEnded.Checked;
        }
        /// <summary>
        /// 定义属性：是否折叠
        /// </summary>
        public bool isVolume
        {
            set => checkBox_volume.Checked = value;
            get => checkBox_volume.Checked;
        }
        public bool isChapter
        {
            set => checkBox_chapter.Checked = value;
            get => checkBox_chapter.Checked;
        }
        public bool isFold
        {
            set => checkBox_fold.Checked = value;
            get => checkBox_fold.Checked;
        }
        public string condition;
        public PlotNode last = null;//上一个
        public PlotNode next = null;//后续
        public PlotNode father = null;//父节点
        public List<PlotNode> branches;//分支
        public DialogNode beginDlg;
        public int branch_index;
        Graphics g;
        public PlotNode()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            beginDlg = new DialogNode(this);
            branches = new List<PlotNode>();
        }
        //返回包括自己在内的节点列表
        public List<PlotNode> getPlotNodeList()
        {
            List<PlotNode> nexts = new List<PlotNode>();
            PlotNode cur = this;
            while (cur != null)
            {
                nexts.Add(cur);
                cur = cur.next;
            }
            return nexts;
        }
        public XmlElement toXml(XmlDocument doc)
        {
            XmlElement xe_plotNodeList = doc.CreateElement("plotNodeList");
            List<PlotNode> plot_list = getPlotNodeList();
            foreach(PlotNode pn in plot_list)
            {
                XmlElement xe_node = doc.CreateElement("plotNode");
                xe_node.SetAttribute("plotName", pn.plotName);
                xe_node.SetAttribute("condition", pn.condition);
                xe_node.SetAttribute("isEnded", pn.isEnded.ToString());
                xe_node.SetAttribute("isFold", pn.isFold.ToString());
                xe_node.SetAttribute("isVolume", pn.isVolume.ToString());
                xe_node.SetAttribute("isChapter", pn.isChapter.ToString());
                XmlElement xe_branch_list = doc.CreateElement("branchList");
                XmlElement xe_dlgs = beginDlg.ToXml(doc);
                xe_node.AppendChild(xe_dlgs);
                foreach(PlotNode branch in pn.branches)
                {
                    xe_branch_list.AppendChild(branch.toXml(doc));
                }
                xe_node.AppendChild(xe_branch_list);
                xe_plotNodeList.AppendChild(xe_node);
            }
            
            return xe_plotNodeList;
        }
        //自动放置剧情节点
        public void Place(int x, int y)
        {
            this.Left = x;
            this.Top = y;
            if (isEnded) return;
            if (next != null)
                this.next.Place(x + this.getBranchesMaxLength() * (this.Width + w), y);
            int sum_branch_height = 0;
            for (int branch_count = 1; branch_count <= branches.Count; branch_count++)
            {
                PlotNode branch = branches[branch_count - 1];
                branch.branch_index = branch_count - 1;
                branch.Place(x + branch.Width + w, y - sum_branch_height - branch.Height - h);
                sum_branch_height += branch.getMaxHeight();
            }
        }
        /*public int getMaxHeight()
        {
            if (branches.Count == 0)
                if (next != null)
                    return next.getMaxHeight();
                else return 1;
            else
            {
                int height = 1;
                foreach (PlotNode branch in branches)
                {
                    if ((bool)(branch.father?.isFold)) continue;
                    int h = branch.getMaxHeight();
                    height += h;
                }
                if (next != null)
                {
                    int h_ = next.getMaxHeight();
                    if (h_ > height) height = h_;
                }
                return height;
            }
        }*/
        public int getMaxHeight()
        {
            int height = Height + h;
            foreach(PlotNode branch in branches)
            {
                height += branch.getMaxHeight();
            }
            if (next == null)
                return height;
            else
            {
                int nextH = next.getMaxHeight();
                if (nextH > height) return nextH;
                else return height;
            }
        }
        //获取最长分支的长度
        public int getBranchesMaxLength()
        {
            int max_len = 0;
            foreach (PlotNode branch in branches)
            {
                if ((bool)(branch.father?.isFold)) continue;
                int len = branch.getNodeLength();
                if (len > max_len) max_len = len;
            }
            return 1 + max_len;
        }  
        //计算这一个剧情节点最长的长度
        public int getNodeLength()
        {
            PlotNode next = this;
            int len = 0;
            while (next != null)
            {
                len += next.getBranchesMaxLength();
                next = next.next;
            }
            return len;
        }
        public void refreshLine()
        {
            g.Clear(Color.White);
            Program.mainform.DrawLine(Program.mainform.beginNode, g);
        }
        //添加后续被点击
        private void addNextClick(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if(next == null)
            {
                    this.next = new PlotNode() { father = this.father, last = this};
            }
            else
            {
                PlotNode n = new PlotNode() { father = this.father, last = this};
                n.next = this.next;
                next = n;
            }
            Program.mainform.refreshPlot();
            refreshLine();
        }
        //添加分支被点击
        private void addBranchClick(object sender, LinkLabelLinkClickedEventArgs e)
        {
            branches.Add(new PlotNode() { father = this, last = null});
            Program.mainform.refreshPlot();
            refreshLine();
        }
        private void PlotNode_Load(object sender, EventArgs e)
        {
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            g = Program.mainform.CreateGraphics();
            //beginDlg = new DialogNode(this);
            refreshDlg();
            Program.mainform.refreshPlot();
        }
        //节点被双击
        private void PlotNode_DoubleClick(object sender, EventArgs e)
        {
            Console.WriteLine(toXml(new XmlDocument()).OuterXml);
        }
        //标签被双击，开始编辑剧情名
        private void OnEditName(object sender, EventArgs e)
        {
            //string newname = Interaction.InputBox("请输入这段剧情的名字：","剧情重命名",plotName);
            text_plotName.Text = plotName;
            text_plotName.Visible = true;
            //if (newname != "") plotName = newname;
        }
        //剧情名编辑框按下某个键
        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode != Keys.Enter) return;
            if (text_plotName.Text != "")
            {
                plotName = text_plotName.Text;
                text_plotName.Visible = false;
            }
        }
        private void OnMouseDown(object sender, MouseEventArgs e)
        {
            moveFlag = true;
            x = e.X;
            y = e.Y;
        }
        private PlotNode getRoot(PlotNode pn)
        {
            PlotNode root = pn;
            while (root.father != null) root = root.father;
            return root;
        }
        private void OnMouseUp(object sender, MouseEventArgs e)
        {
            moveFlag = false;
            Program.mainform.refreshPlot();
            refreshLine();
        }
        private void delNodeClick(object sender, LinkLabelLinkClickedEventArgs e)
        {
            //todo:
            if (last == null)
            {
                //第一个节点
                if(father == null)
                {
                    //根节点，不能删除
                    return;
                }
                else
                {
                    if(this.branches.Count != 0 || this.next != null)
                    {
                        if(MessageBox.Show("当前节点为分支根节点，且有分支或后续。\n删除该节点后，其分支和后续都将被一并删除。\n确定要删除吗？", "确定删除",MessageBoxButtons.YesNo) == DialogResult.Yes)
                        {
                            father.branches.RemoveAt(branch_index);
                        }
                    }
                    else
                        father.branches.RemoveAt(branch_index);

                }
            }
            else
            {
                //普通节点
                this.last.next = this.next;
            }
            Program.mainform.refreshPlot();
        }
        private void checkBox_fold_CheckedChanged(object sender, EventArgs e)
        {
            Program.mainform.refreshPlot();
        }
        private void checkbox_isEnded_CheckedChanged(object sender, EventArgs e)
        {
            Program.mainform.refreshPlot();
        }
        private void checkBox_foldDlg_CheckedChanged(object sender, EventArgs e)
        {
            refreshDlg();
        }
        private void OnFocusLosed(object sender, EventArgs e)
        {
            plotName = text_plotName.Text;
            text_plotName.Visible = false;
        }

        private void changeColor()
        {
            if(checkBox_chapter.Checked)
            {
                this.BackColor = Color.FromArgb(255, 255, 255, 192);
            }
            else if (checkBox_volume.Checked)
            {
                this.BackColor = Color.FromArgb(255, 192, 255, 255);
            }
            else
            {
                this.BackColor = Color.DarkGray;
            }
        }

        private void checkBox_volume_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_chapter.Checked && checkBox_volume.Checked)
                checkBox_chapter.Checked = false;
            changeColor();
        }

        private void checkBox_chapter_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox_chapter.Checked && checkBox_volume.Checked)
                checkBox_volume.Checked = false;
            changeColor();
        }

        private void editCondClick(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if(father == null)
            {
                MessageBox.Show("该节点为根节点，无法添加跳转条件!", "添加条件", MessageBoxButtons.OK);
                return;
            }
            string _condition = Interaction.InputBox("请输入跳转到该分支的条件", "条件编辑", condition);
            if (_condition != "")
                condition = _condition;
            Program.mainform.refreshPlot();
        }

        private void checkbox_isEnded_CheckStateChanged(object sender, EventArgs e)
        {
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (moveFlag && father == null && last == null)
            {
                Left += e.X - x;
                Top += e.Y - y;
            }

        }
        public void refreshDlg()
        {
            flowLayoutPanel1.Controls.Clear();
            if (checkBox_foldDlg.Checked) return;
            beginDlg.refreshId();
            flowLayoutPanel1.Controls.Add(beginDlg);
            DialogNode curDlg = beginDlg;
            while(curDlg.next != null)
            {
                if (curDlg.Fold == false) 
                {
                    curDlg.next.refreshId();
                    flowLayoutPanel1.Controls.Add(curDlg.next);
                    curDlg = curDlg.next;
                }
                else
                {
                    break;
                }
            }
            Program.mainform.refreshPlot();
        }     
    }
}
